package com.fileUpload.utilities.unpack;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.upload.DiskFile;
import org.apache.struts.upload.FormFile;

import com.fileUpload.utilities.UploadUtil;

import de.innosystec.unrar.Archive;
import de.innosystec.unrar.exception.RarException;
import de.innosystec.unrar.rarfile.FileHeader;

/**
 * 
 * <一句话功能简述> <功能详细描述>
 * 
 * @author eric.zhang
 * @version [版本号, 2009-11-27]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class ExtractRarArchive
{

    private static Log logger = LogFactory.getLog(ExtractRarArchive.class.getName());

    /** 系统临时目录 */
    private static String SYSTMPDIR = System.getProperty("java.io.tmpdir");

    public static List<FormFile> extractArchive(String archive, String destination)
    {
        if (archive == null || destination == null)
        {
            throw new RuntimeException("archive and destination must me set");
        }
        File arch = new File(archive);
        if (!arch.exists())
        {
            throw new RuntimeException("the archive does not exit: " + archive);
        }
        File dest = new File(destination);
        if (!dest.exists() || !dest.isDirectory())
        {
            dest.mkdirs();
            // throw new
            // RuntimeException("the destination must exist and point to a directory: "
            // + destination);
        }
        return extractArchive(arch, dest);
    }

    public static List<FormFile> extractArchive(File archive, File destination)
    {
        List<FormFile> fileList = new ArrayList<FormFile>();
        String[] fileTypes = new String[]{"rar", "zip", "doc", "txt", "pdf", "rtf", "ppt", "jpg", "xls", "html", "mht", "htm"};
//        String[] fileTypes = AceonaConfig.getConfig(ConfigKeys.RESUME_TYPE).split(",");
        Archive arch = null;
        try
        {
            arch = new Archive(archive);
        }
        catch (RarException e)
        {
            logger.error(e);
        }
        catch (IOException e1)
        {
            logger.error(e1);
        }
        catch (Exception e)
        {
            logger.error(e);
            return fileList;
        }
        if (arch != null)
        {
            if (arch.isEncrypted())
            {
                logger.warn("archive is encrypted cannot extreact");
                return fileList;
            }
            FileHeader fh = null;
            while (true)
            {
                fh = arch.nextFileHeader();
                if (fh == null)
                {
                    break;
                }
                if (fh.isEncrypted())
                {
                    logger.warn("file is encrypted cannot extract: " + fh.getFileNameString());
                    continue;
                }
                logger.info("extracting: " + fh.getFileNameString());
                try
                {
                    if (fh.isDirectory())
                    {
                        createDirectory(fh, destination);
                    }
                    else
                    {
                        File f = createFile(fh, destination);
                        OutputStream stream = new FileOutputStream(f);
                        arch.extractFile(fh, stream);
                        stream.close();
                        // 增加已解压文件列表,如果类型符合简历格式
                        if (UploadUtil.checkTypes(fileTypes, f.getName().split("\\.")))
                        {
                            if (!(UploadUtil.TYPERAR.equalsIgnoreCase(UploadUtil.subFileType(f.getName())) || UploadUtil.TYPEZIP.equalsIgnoreCase(UploadUtil.subFileType(f.getName()))))
                            {
                                FormFile tempFile = new DiskFile(f.getAbsolutePath());
                                tempFile.setFileSize((int) f.length());
                                tempFile.setFileName(f.getName());
                                fileList.add(tempFile);
                            }
                        }
                    }
                }
                catch (IOException e)
                {
                    logger.error("error extracting the file", e);
                }
                catch (RarException e)
                {
                    logger.error("error extraction the file", e);
                }
                catch (Exception e)
                {
                    logger.error("error extraction the file", e);
                }
            }
        }
        return fileList;
    }

    private static File createFile(FileHeader fh, File destination)
    {
        File f = null;
        String name = null;
        if (fh.isFileHeader() && fh.isUnicode())
        {
            name = fh.getFileNameW();
        }
        else
        {
            name = fh.getFileNameString();
        }
        f = new File(destination, name);
        if (!f.exists())
        {
            try
            {
                f = makeFile(destination, name);
            }
            catch (IOException e)
            {
                logger.error("error creating the new file: " + f.getName(), e);
            }
        }
        return f;
    }

    private static File makeFile(File destination, String name) throws IOException
    {
        String[] dirs = name.split("\\\\");
        if (dirs == null)
        {
            return null;
        }
        String path = "";
        int size = dirs.length;
        if (size == 1)
        {
            return new File(destination, name);
        }
        else if (size > 1)
        {
            for (int i = 0; i < dirs.length - 1; i++)
            {
                path = path + File.separator + dirs[i];
                new File(destination, path).mkdir();
            }
            path = path + File.separator + dirs[dirs.length - 1];
            File f = new File(destination, path);
            f.createNewFile();
            return f;
        }
        else
        {
            return null;
        }
    }

    private static void createDirectory(FileHeader fh, File destination)
    {
        File f = null;
        if (fh.isDirectory() && fh.isUnicode())
        {
            f = new File(destination, fh.getFileNameW());
            if (!f.exists())
            {
                makeDirectory(destination, fh.getFileNameW());
            }
        }
        else if (fh.isDirectory() && !fh.isUnicode())
        {
            f = new File(destination, fh.getFileNameString());
            if (!f.exists())
            {
                makeDirectory(destination, fh.getFileNameString());
            }
        }
    }

    private static void makeDirectory(File destination, String fileName)
    {
        String[] dirs = fileName.split("\\\\");
        if (dirs == null)
        {
            return;
        }
        String path = "";
        for (String dir : dirs)
        {
            path = path + File.separator + dir;
            new File(destination, path).mkdir();
        }
    }

    public static List<FormFile> extractArchive(FormFile formFile)
    {
        // 通过FormFile获取文件流
        // 1,将文件流存入系统临时根目录2,解压根目录文件,并存入临时目录3,遍历此临时目录,将文件列表路径以list输出
        String tempFormFilePath = SYSTMPDIR + File.separator + formFile.hashCode() + formFile.getFileName();
        String tempFormFileExtractPath = SYSTMPDIR + File.separator + formFile.hashCode();
        boolean fileOk = false;
        try
        {
            fileOk = UploadUtil.saveFile(formFile.getInputStream(), tempFormFilePath);
            // 存文件进入临时目录成功
            if (fileOk)
            {
                // 开始解压到临时目录
                return extractArchive(tempFormFilePath, tempFormFileExtractPath);
            }
        }
        catch (FileNotFoundException e)
        {

        }
        catch (IOException e)
        {

        }
        return null;
    }

    public static void main(String[] args)
    {
        // if (args.length == 2)
        // {
        // extractArchive(args[0], args[1]);
        // }
        // else
        // {
        // System.out.println("usage: java -jar extractArchive.jar <thearchive> <the destination directory>");
        // }
        extractArchive("D:\\workspace10\\test\\rarpack\\JAVA高性能.rar", "D:\\workspace10\\test\\unrarpack\\JAVA高性能");
        // extractArchive("D:\\workspace10\\test\\rarpack\\jsp_tupian (1).rar",
        // "D:\\workspace10\\test\\unrarpack\\jsp_tupian (1)");
        // extractArchive("D:\\workspace10\\test\\rarpack\\JSTL详解.rar",
        // "D:\\workspace10\\test\\unrarpack\\JSTL详解");
        // extractArchive("D:\\workspace10\\test\\rarpack\\SupLogin.rar",
        // "D:\\workspace10\\test\\unrarpack\\SupLogin");
        // extractArchive("D:\\workspace10\\test\\rarpack\\活动照片.rar",
        // "D:\\workspace10\\test\\unrarpack\\活动照片");
    }
}
